# 代码执行流程说明：
# 正向传播阶段：
# 苹果价格计算：100 × 2 = 200
# 橘子价格计算：150 × 3 = 450
# 价格汇总：200 + 450 = 650
# 含税计算：650 × 1.1 = 715
# 反向传播阶段：
# 从最终价格715开始反向传播(初始梯度dprice=1)
# 税费层反向传播：计算对总价和税率的梯度
# 加法层反向传播：计算对苹果和橘子价格的梯度
# 乘法层反向传播：计算对单价和数量的梯度
# 梯度验证：
# 每个参数的梯度都符合数学上的偏导数计算
# 展示了计算图中梯度是如何从输出层反向传播到输入层的
# 这个示例演示了：
# 如何构建多层计算图
# 正向传播计算预测值
# 反向传播自动计算梯度
# 梯度值的实际意义解释
# 为理解神经网络的反向传播机制提供了直观示例

# 指定文件编码为UTF-8
# coding: utf-8

"""
buy_apple_orange.py 功能说明：
1. 演示使用计算图实现购买苹果和橘子的总价计算
2. 包含完整的正向传播(计算总价)和反向传播(计算梯度)过程
3. 模拟场景：购买苹果(单价100元)2个，橘子(单价150元)3个，消费税1.1倍
4. 展示多层计算图中梯度的反向传播过程

关键点：
- 使用乘法层(MulLayer)处理单价×数量
- 使用加法层(AddLayer)处理苹果和橘子的价格汇总
- 最后使用乘法层处理消费税
- 反向传播时梯度会按照计算图的相反方向传递
- 验证各参数的梯度计算是否正确
"""

# 从layer_naive模块导入所有类和方法
from layer_naive import *

# 定义初始参数
apple = 100       # 苹果单价
apple_num = 2     # 苹果数量
orange = 150      # 橘子单价
orange_num = 3    # 橘子数量
tax = 1.1         # 消费税税率

# 创建各计算层实例
mul_apple_layer = MulLayer()         # 苹果价格计算层(单价×数量)
mul_orange_layer = MulLayer()        # 橘子价格计算层(单价×数量)
add_apple_orange_layer = AddLayer()  # 价格汇总层(苹果+橘子)
mul_tax_layer = MulLayer()           # 税费计算层(总价×税率)

# ========== 正向传播 ===# ... 省略其他代码 ...


# ==== 修改后代码 ====
# (1) 计算苹果总价：100 × 2 = 200
apple_price = mul_apple_layer.forward(apple, apple_num)
# (2) 计算橘子总价：150 × 3 = 450
orange_price = mul_orange_layer.forward(orange, orange_num)
# (3) 计算水果总价：200 + 450 = 650
all_price = add_apple_orange_layer.forward(apple_price, orange_price)
# (4) 计算含税总价：650 × 1.1 = 715
price = mul_tax_layer.forward(all_price, tax)

# ========== 反向传播 ===# ... 省略其他代码 ...


# ==== 修改后代码 ====
# 从最终价格开始反向传播(初始梯度为1)
dprice = 1
# (4) 计算税费层的梯度：dall_price=1.1, dtax=650
dall_price, dtax = mul_tax_layer.backward(dprice)
# (3) 计算加法层的梯度：dapple_price=1.1, dorange_price=1.1
dapple_price, dorange_price = add_apple_orange_layer.backward(dall_price)
# (2) 计算橘子层的梯度：dorange=3.3, dorange_num=165
dorange, dorange_num = mul_orange_layer.backward(dorange_price)
# (1) 计算苹果层的梯度：dapple=2.2, dapple_num=110
dapple, dapple_num = mul_apple_layer.backward(dapple_price)

# 打印计算结果
print("price:", int(price))             # 总价：715
print("dApple:", dapple)                # 苹果单价梯度：2.2
print("dApple_num:", int(dapple_num))   # 苹果数量梯度：110
print("dOrange:", dorange)              # 橘子单价梯度：3.3
print("dOrange_num:", int(dorange_num)) # 橘子数量梯度：165
print("dTax:", dtax)                    # 税率梯度：650

"""
输出结果分析：
price: 715             # 100×2 + 150×3 = 650 → 650×1.1=715
dApple: 2.2            # ∂price/∂apple = num×tax = 2×1.1 = 2.2
dApple_num: 110        # ∂price/∂apple_num = apple×tax = 100×1.1 = 110
dOrange: 3.3           # ∂price/∂orange = num×tax = 3×1.1 = 3.3
dOrange_num: 165       # ∂price/∂orange_num = orange×tax = 150×1.1 = 165
dTax: 650              # ∂price/∂tax = all_price = 650
"""
